#include "ConfigElement.h"
#include "UnknownElement.h"

using namespace log4cplus;

namespace OpenNano
{
    ConfigElement::ConfigElement(TiXmlElement * element) :
            el(element), _children(), _attribs(), _text(), _processed(false), logger(Logger::getInstance("ConfigElement"))
    {
        el = element;
    }


    bool ConfigElement::process()
    {
        if (_processed) return false;
        if (!el) return false;

        TiXmlAttribute * attrib = el->FirstAttribute();
        while (attrib)
        {
            attributeFound( attrib );
            attrib = attrib->Next();
        }
        TiXmlElement * child = el->FirstChildElement();
        while (child)
        {
            childElementFound( child );
            child = child->NextSiblingElement();
        }
        const char * str = el->GetText();
        if (str)
        {
            textFound(str);
        }
        _processed=true;
        return postConfiguration();
    }

    TiXmlElement * ConfigElement::getTiXmlElement()
    {
        return el;
    }

    ConfigElement::~ConfigElement()
    {
    }


    void ConfigElement::unknownAttributeFound(TiXmlAttribute * unknown)
    {
        std::string _name = unknown->NameTStr();
        std::string _value = unknown->ValueStr();
        _attribs[_name]=_value;
    }

    void ConfigElement::unknownElementFound(TiXmlElement * unknown)
    {
        std::string name = unknown->ValueStr();
        UnknownElement * _u = (UnknownElement *) ConfigElementFactory::getInstance().create(UNKNOWN_ELEMENT)(unknown);

        //_children[name] = _u;
        if (_u)
        {
            _u->process(); //always true;
            _children[name]=_u;
        }
        else
        {
            //NOTE_TO_SELF:
            //unknown element couldn't be created
            //throw an error!
            LOG4CPLUS_ERROR(logger, "unknown element couldn't be created!");
        }

    }

    void ConfigElement::unknownTextFound(const char * text)
    {
        _text= text;
    }


    const std::string & ConfigElement::getUnknownText() const
    {
        return _text;
    }

    const UnknownElementsList & ConfigElement::getUnknownElements() const
    {
        return _children;
    }

    const UnknownAttributesList & ConfigElement::getUnknownAttributes() const
    {
        return _attribs;
    }

    UnknownElement * ConfigElement::getUnknownElement(const std::string& name)
    {
        UnknownElement * unkn = 0;
        UnknownElementsList::iterator it = _children.find(name);
        if ( it != _children.end() )
        {
            unkn = it->second;
        }
        else
        {
            LOG4CPLUS_WARN(logger, "Element not found:");
            LOG4CPLUS_WARN(logger, name);
        }
        return unkn;
    }

    bool ConfigElement::getUnknownAttribute(const std::string& name, std::string &value)
    {
        bool attribute_found = false;
        UnknownAttributesList::iterator it = _attribs.find(name);
        if ( it!= _attribs.end() )
        {
            value=it->second;
            attribute_found=true;
        }
        else
        {
            LOG4CPLUS_WARN(logger, "Attribute not found:");
            LOG4CPLUS_WARN(logger, name);
        }
        return attribute_found;

    }

}
